package upnp

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

// FROM: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
// Device description section, only include REQUIRED fields
type descResponse struct {
	// configuration number to which the device description belongs
	ConfigID string `xml:"configId,attr"`
	// version templates
	SpecVersion specVersionType `xml:"specVersion"`
	// device object
	Device deviceType `xml:"device"`
}

type specVersionType struct {
	Major int `xml:"major"`
	Minor int `xml:"minor"`
}

type deviceType struct {
	// starts with "urn:schemas-upnp-org:device:"
	DeviceType string `xml:"deviceType"`
	// show name
	FriendlyName string `xml:"friendlyName"`
	// manufacturer name
	Manufacturer string `xml:"manufacturer"`
	// model name
	ModelName string `xml:"modelName"`
	// service list
	ServiceList []serviceType `xml:"serviceList>service"`
	// embedded devices
	DeviceList []deviceType `xml:"deviceList>device"`
}

type serviceType struct {
	// starts with "urn:schemas-upnp-org:service:"
	ServiceType string `xml:"serviceType"`
	// starts with "urn:upnp-org:serviceId:"
	ServiceID string `xml:"serviceId"`
	// url for service spec
	SCPDURL string `xml:"SCPDURL"`
	// url for control
	ControlURL string `xml:"controlURL"`
	// url for eventing
	EventSubURL string `xml:"eventSubURL"`
}

func (d *Device) parse() error {
	resp, err := http.Get(d.descLocation)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		data, _ := ioutil.ReadAll(resp.Body)
		return fmt.Errorf("GET description info fail, http_code=%d\n%s", resp.StatusCode, string(data))
	}
	var desc descResponse
	if err := xml.NewDecoder(resp.Body).Decode(&desc); err != nil {
		return err
	}
	if err := d.loadService(desc.Device); err != nil {
		return err
	}
	d.parsed = true
	return nil
}
